#ifdef SHT15_ENABLE
//logMessage(LOGLEVEL_DEBUG, "SHT15", "", "");

int SHT15TempCmd  = 0b00000011;
int SHT15HumidCmd = 0b00000101;
unsigned long SHT15PreviousMillis;
float SHT15Temperature[SHT15SENSORS];
float SHT15humidity[SHT15SENSORS];
float SHT15humidityMin[SHT15SENSORS];
float SHT15humidityMax[SHT15SENSORS];
float SHT15temperatureMin[SHT15SENSORS];
float SHT15temperatureMax[SHT15SENSORS];

/*************************************** 
 * 
 * global functions
 *
 ***************************************/
void setupSHT15() {
  logMessage(LOGLEVEL_INFO, "SHT15", "setup SHT15", "");
  initSHT15MinMaxValues();
  readSHT15Values();   
}

void readSHT15ValuesDelay() {
  unsigned long tempCurrentMillis = millis();
  if((tempCurrentMillis - SHT15PreviousMillis) > SHT15READING_DELAY || SHT15PreviousMillis == 0) {    
    SHT15PreviousMillis = tempCurrentMillis;  
    readSHT15Values(); 
  }
}

void readSHT15Values() {
    float tempValues[SHT15SENSORS];
    for (int i=0; i<SHT15SENSORS; i++) {
      tempValues[i] = readSHT15Temperature(SHT15_dataPin[i], SHT15_clockPin[i]);
    }
    setSHT15Temperature(tempValues);
    for (int i=0; i<SHT15SENSORS; i++) {
      tempValues[i] = readSHT15Humidity(SHT15_dataPin[i], SHT15_clockPin[i]);
    }
    setSHT15Humidity(tempValues);    
}

float* getSHT15Temperature() {
  readSHT15ValuesDelay();
  return SHT15Temperature;
}

float getSHT15Temperature(int anIndex) {
  readSHT15ValuesDelay();
  return SHT15Temperature[anIndex];
}

void setSHT15Temperature(float aTemperature[SHT15SENSORS]) {
  float* tempMinValues = getSHT15TemperatureMin();
  float* tempMaxValues = getSHT15TemperatureMax();
  for (int i = 0; i <SHT15SENSORS; i++) {
    SHT15Temperature[i] = aTemperature[i];
    if (SHT15Temperature[i] > tempMaxValues[i]) {
      tempMaxValues[i] = SHT15Temperature[i];
    }
    if (SHT15Temperature[i] < tempMinValues[i]) {
      tempMinValues[i] = SHT15Temperature[i];
    }      
  }
  setSHT15TemperatureMin(tempMinValues);
  setSHT15TemperatureMax(tempMaxValues);    
}

float* getSHT15Humidity() {
  readSHT15ValuesDelay();
  return SHT15humidity;
}

float getSHT15Humidity(int anIndex) {
  readSHT15ValuesDelay();
  return SHT15humidity[anIndex];
}

void setSHT15Humidity(float aHumidity[SHT15SENSORS]) {
  float* tempMinValues = getSHT15HumidityMin();
  float* tempMaxValues = getSHT15HumidityMax();
  for (int i = 0; i <SHT15SENSORS; i++) {
    SHT15humidity[i] = aHumidity[i];
    if (SHT15humidity[i] > tempMaxValues[i]) {
      tempMaxValues[i] = SHT15humidity[i];
    }
    if (SHT15humidity[i] < tempMinValues[i]) {
      tempMinValues[i] = SHT15humidity[i];
    }   
  }
}

float* getSHT15HumidityMin() {
  return SHT15humidityMin;
}

float getSHT15HumidityMin(int anIndex) {
  return SHT15humidityMin[anIndex];
}

float* setSHT15HumidityMin(float aHumidity[SHT15SENSORS]) {
  for (int i = 0; i <SHT15SENSORS; i++) {
    SHT15humidityMin[i] = aHumidity[i];
  }
}

float* getSHT15HumidityMax() {
  return SHT15humidityMax;
}

float getSHT15HumidityMax(int anIndex) {
  return SHT15humidityMax[anIndex];
}

void setSHT15HumidityMax(float aHumidity[SHT15SENSORS]) {
  for (int i = 0; i <SHT15SENSORS; i++) {
    SHT15humidityMax[i] = aHumidity[i];
  }
}

float* getSHT15TemperatureMin() {
  return SHT15temperatureMin;
}

float getSHT15TemperatureMin(int anIndex) {
  return SHT15temperatureMin[anIndex];
}

void setSHT15TemperatureMin(float aTemperature[SHT15SENSORS]) {
  for (int i = 0; i <SHT15SENSORS; i++) {
    SHT15temperatureMin[i] = aTemperature[i];
  }
}

float* getSHT15TemperatureMax() {
  return SHT15temperatureMax;
}

float getSHT15TemperatureMax(int anIndex) {
  return SHT15temperatureMax[anIndex];
}

void setSHT15TemperatureMax(float aTemperature[SHT15SENSORS]) {
  for (int i = 0; i <SHT15SENSORS; i++) {
    SHT15temperatureMax[i] = aTemperature[i];
  }
}

void initSHT15MinMaxValues() {  
  float tempMin[SHT15SENSORS];
  float tempMax[SHT15SENSORS];
  for (int i = 0; i < SHT15SENSORS; i++) {
    tempMin[i] = 100.0;
    tempMax[i] = 0.0;    
  }
  setSHT15TemperatureMin(tempMin);
  setSHT15TemperatureMax(tempMax);  
  setSHT15HumidityMin(tempMin);
  setSHT15HumidityMax(tempMax);  
}

void resetSHT15MinMax() {
  initSHT15MinMaxValues();
}

 /**
  * prints the temperature and humidiy
  * values of one sensor
  */
void printSerialTemperatureAndHumidity() {    
    #ifdef SHT15_ENABLE
    for (int i=0; i<SHT15SENSORS; i++) {
      Serial.print("Sensor: ");
      Serial.println(i);

      Serial.print("Temp: ");
      Serial.print(getSHT15Temperature(i));
      Serial.print("C (");
      Serial.print(getSHT15TemperatureMin(i));
      Serial.print("/");      
      Serial.print(getSHT15TemperatureMax(i));
      Serial.println(")");
      Serial.print("Rlf: ");
      Serial.print(getSHT15Humidity(i));    
      Serial.print("% (");
      Serial.print(getSHT15HumidityMin(i));
      Serial.print("/");
      Serial.print(getSHT15HumidityMax(i));
      Serial.println(")");
      Serial.println("");
    }
    #endif
    #ifdef LM35_ENABLE
    for (int i=0; i<LM35SENSORS; i++) {
      Serial.print("LM35: ");
      if (LM35SENSORS > 1) {
        Serial.println(i);
      }
      Serial.print("Temp: ");
      Serial.print(getLM35Temperature(i));
      Serial.print("C ("); 
      Serial.print(getLM35TemperatureMin(i));
      Serial.print("/");
      Serial.print(getLM35TemperatureMax(i));
      Serial.println(")"); 
      Serial.println("");      
    }    
    #endif
}
/*************************************** 
 * 
 * Sensor implementation
 *
 ***************************************/

float readSHT15Temperature(int aDataPin, int aClockPin) {   
   sendCommandSHT(SHT15TempCmd, aDataPin, aClockPin);
   waitForResultSHT(aDataPin);
   float tempVal = getData16SHT(aDataPin, aClockPin);
   skipCrcSHT(aDataPin, aClockPin);
   float tempTemp = (tempVal * 0.01) + -40.1;
   return tempTemp;
}

float readSHT15Humidity(int aDataPin, int aClockPin) {
   sendCommandSHT(SHT15HumidCmd, aDataPin, aClockPin);
   waitForResultSHT(aDataPin);
   int tempVal = getData16SHT(aDataPin, aClockPin);
   skipCrcSHT(aDataPin, aClockPin);
   float tempHum = -4.0 + 0.0405 * tempVal + -0.0000028 * tempVal * tempVal;
   return tempHum;
}

int shiftIn(int aDataPin, int aClockPin, int aNumBits) {
   int ret = 0;
   int i;

   for (i=0; i<aNumBits; ++i) {
      digitalWrite(aClockPin, HIGH);
      delay(10);  // I don't know why I need this, but without it I don't get my 8 lsb of temp
      ret = ret*2 + digitalRead(aDataPin);
      digitalWrite(aClockPin, LOW);
   }

   return(ret);
}

void sendCommandSHT(int aCommand, int aDataPin, int aClockPin) {
  int tempAck;

  // Transmission Start
  pinMode(aDataPin, OUTPUT);
  pinMode(aClockPin, OUTPUT);
  digitalWrite(aDataPin, HIGH);
  digitalWrite(aClockPin, HIGH);
  digitalWrite(aDataPin, LOW);
  digitalWrite(aClockPin, LOW);
  digitalWrite(aClockPin, HIGH);
  digitalWrite(aDataPin, HIGH);
  digitalWrite(aClockPin, LOW);
           
  // The command (3 msb are address and must be 000, and last 5 bits are command)
  shiftOut(aDataPin, aClockPin, MSBFIRST, aCommand);

  // Verify we get the coorect ack
  digitalWrite(aClockPin, HIGH);
  pinMode(aDataPin, INPUT);
  tempAck = digitalRead(aDataPin);
  if (tempAck != LOW) {
    String tempMessage = "SHT15: Error while handshake1 " + String(tempAck);
    Serial.println(tempMessage);
    //logMessage(LOGLEVEL_ERROR,"SHT15", "Error while handshake1 ", String(tempAck));
  }
  digitalWrite(aClockPin, LOW);
  tempAck = digitalRead(aDataPin);
  if (tempAck != HIGH) {
    String tempMessage = "SHT15: Error while handshake2 " + String(tempAck);
    Serial.println(tempMessage);
    //logMessage(LOGLEVEL_ERROR,"SHT15", "Error while handshake2 ", String(tempAck));
  }
}

void waitForResultSHT(int aDataPin) {
  int i;
  int tempAck;
  
  pinMode(aDataPin, INPUT);
  
  for(i= 0; i < 100; ++i) {
    delay(10);
    tempAck = digitalRead(aDataPin);

    if (tempAck == LOW)
      break;
  }
  
  if (tempAck == HIGH) {
    String tempMessage = "SHT15: Error while waiting for result of sensor 0";
    Serial.println(tempMessage);
    //logMessage(LOGLEVEL_ERROR,"SHT15", "Error while waiting for result of sensor", 0);
  }
}

int getData16SHT(int aDataPin, int aClockPin) {
  int tempVal;
  
  // Get the most significant bits
  pinMode(aDataPin, INPUT);
  pinMode(aClockPin, OUTPUT);
  tempVal = shiftIn(aDataPin, aClockPin, 8);
  tempVal *= 256;

  // Send the required ack
  pinMode(aDataPin, OUTPUT);
  digitalWrite(aDataPin, HIGH);
  digitalWrite(aDataPin, LOW);
  digitalWrite(aClockPin, HIGH);
  digitalWrite(aClockPin, LOW);
           
  // Get the lest significant bits
  pinMode(aDataPin, INPUT);
  tempVal |= shiftIn(aDataPin, aClockPin, 8);

  return tempVal;
}

void skipCrcSHT(int aDataPin, int aClockPin) {
  // Skip acknowledge to end trans (no CRC)
  pinMode(aDataPin, OUTPUT);
  pinMode(aClockPin, OUTPUT);

  digitalWrite(aDataPin, HIGH);
  digitalWrite(aClockPin, HIGH);
  digitalWrite(aClockPin, LOW);
}
#endif
